package com.huanqiu.mylib.util;

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class LogUtil {

    // 写文件配置
    public static final int CONFIG_WRITE_FILE_NONE = 1; // 不写文件 (默认值)
    public static final int CONFIG_WRITE_FILE_WE = 2;   // 只有 w e 写文件
    public static final int CONFIG_WRITE_FILE_ALL = 3;  // v i d w e 都写文件

//    private static boolean isEnable = BuildConfig.DEBUG; // 是否需要打印 log
    private static boolean isEnable = true;

    private static boolean V_writeFile = false;
    private static boolean I_writeFile = false;
    private static boolean D_writeFile = false;
    private static boolean W_writeFile = false;
    private static boolean E_writeFile = false;

    private static Context sContext;
    private static String sLogFilePath;
    private static DateFormat sDateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");

    private LogUtil() {
        /* cannot be instantiated */
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    public static void v(String tag, String msg) {
        if (isEnable) {
            Log.v(tag, msg);
            if (V_writeFile)
                log2file("V/" + tag, msg, null);
        }
    }

    public static void i(String tag, String msg) {
        if (isEnable) {
            Log.i(tag, msg);
            if (I_writeFile)
                log2file("I/" + tag, msg, null);
        }
    }

    public static void d(String tag, String msg) {
        if (isEnable) {
            Log.d(tag, msg);
            if (D_writeFile)
                log2file("D/" + tag, msg, null);
        }
    }

    public static void w(String tag, String msg) {
        if (isEnable) {
            Log.w(tag, msg);
            if (W_writeFile)
                log2file("W/" + tag, msg, null);
        }
    }

    public static void e(String tag, String msg) {
        if (isEnable) {
            Log.e(tag, msg);
            if (E_writeFile)
                log2file("E/" + tag, msg, null);
        }
    }

    public static void setContext(Context context) {
        sContext = context;
        // todo-副作用
        if (context != null) {
            sLogFilePath = context.getFilesDir().getAbsolutePath() + "/log_20210101.txt";
        }
    }

    // 打开/关闭 Log 开关
    public static void enableLog(boolean enable) {
        if (enable == isEnable) return;
        if (enable) {
            isEnable = true;
            LogUtil.d("aaa", "====== 打开 Log 开关 ======");
        } else {
            LogUtil.d("aaa", "====== 关闭 Log 开关 ======");
            isEnable = false;
        }
    }

    public static void configWriteFile(int config) {
        switch (config) {
            case CONFIG_WRITE_FILE_NONE:
                V_writeFile = false;
                I_writeFile = false;
                D_writeFile = false;
                W_writeFile = false;
                E_writeFile = false;
                break;
            case CONFIG_WRITE_FILE_WE:
                V_writeFile = false;
                I_writeFile = false;
                D_writeFile = false;
                W_writeFile = true;
                E_writeFile = true;
                break;
            case CONFIG_WRITE_FILE_ALL:
                V_writeFile = true;
                I_writeFile = true;
                D_writeFile = true;
                W_writeFile = true;
                E_writeFile = true;
                break;
        }
    }

    public static String getLogFilePath() {
        return sLogFilePath;
    }

    // 获取 Throwable 的堆栈信息
    public static String getThrowableMsg(Throwable t) {
        if (t == null)
            return "";

        StringBuilder sb = new StringBuilder();
        sb.append(t.toString());
        sb.append("\n");

        StackTraceElement[] stack = t.getStackTrace();
        for (StackTraceElement a : stack) {
            sb.append("\t\t\t");
            sb.append(a.toString());
            sb.append("\n");
        }

        return sb.toString();
    }

    // 把 log 写入文件
    private static synchronized void log2file(String tag, String msg, Throwable t) {
        if (sLogFilePath == null) return;

        tag = getCurTime() + " " + tag; // 在 tag 前添加当前时间

        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(sLogFilePath, "rw");
            raf.seek(raf.length());

            raf.write(tag.getBytes());
            raf.write(": ".getBytes());
            raf.write(msg.getBytes());
            raf.write("\n".getBytes());

            if (t != null) {
                raf.write(getThrowableMsg(t).getBytes());
                raf.write("\n".getBytes());
            }
            raf.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf != null) {
                try {
                    raf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static String getCurTime() {
        long time = System.currentTimeMillis();
        Date now = new Date(time);
        return sDateFormat.format(now) + String.format(Locale.getDefault(), ".%03d", time % 1000);
    }

}
